home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / bin / euse < prev    next >
Text File  |  2006-05-08  |  12KB  |  413 lines

  1. #!/bin/bash
  2.  
  3. # $Header$
  4.  
  5. # bash replacement for the original euse by Arun Bhanu
  6. # Author: Marius Mauch <genone@gentoo.org>
  7. # Version: 0.2
  8. # Licensed under the GPL v2
  9.  
  10. PROGRAM_NAME=euse
  11. PROGRAM_VERSION=0.1
  12.  
  13. MAKE_CONF_PATH=/etc/make.conf
  14. MAKE_GLOBALS_PATH=/etc/make.globals
  15. MAKE_PROFILE_PATH=/etc/make.profile
  16. MAKE_CONF_BACKUP_PATH=/etc/make.conf.euse_backup
  17.  
  18. [ -z "${MODE}" ] && MODE="showhelp"        # available operation modes: showhelp, showversion, showdesc, showflags, modify
  19.  
  20. parse_arguments() {
  21.     if [ -z "${1}" ]; then
  22.         return
  23.     fi
  24.     while [ -n "${1}" ]; do
  25.         case "${1}" in
  26.             -h | --help)    MODE="showhelp";;
  27.             -v | --version) MODE="showversion";;
  28.             -i | --info)    MODE="showdesc";;
  29.             -l | --local)   SCOPE="local";;
  30.             -g | --global)  SCOPE="global";;
  31.             -a | --active)  MODE="showflags";;
  32.             -E | --enable)  MODE="modify"; ACTION="add";;
  33.             -D | --disable) MODE="modify"; ACTION="remove";;
  34.             -P | --prune)   MODE="modify"; ACTION="prune";;
  35.             -*)
  36.                 echo "ERROR: unknown option ${1} specified."
  37.                 echo
  38.                 MODE="showhelp"
  39.                 ;;
  40.             *)
  41.                 ARGUMENTS="${ARGUMENTS} ${1}"
  42.                 ;;
  43.         esac
  44.         shift
  45.     done
  46. }
  47.  
  48. error() {
  49.     echo "ERROR: ${1}"
  50.     set +f
  51.     exit 1
  52. }
  53.  
  54. check_sanity() {
  55.     # file permission tests
  56.     local descdir
  57.     
  58.     descdir="$(get_portdir)/profiles"
  59.     
  60.     [ ! -r "${MAKE_CONF_PATH}" ] && error "${MAKE_CONF_PATH} is not readable"
  61.     [ ! -r "${MAKE_GLOBALS_PATH}" ] && error "${MAKE_GLOBALS_PATH} is not readable"
  62.     [ ! -h "${MAKE_PROFILE_PATH}" ] && error "${MAKE_PROFILE_PATH} is not a symlink"
  63.     [ -z "$(get_portdir)" ] && error "\$PORTDIR couldn't be determined"
  64.     [ ! -d "${descdir}" ] && error "${descdir} does not exist or is not a directory"
  65.     [ ! -r "${descdir}/use.desc" ] && error "${descdir}/use.desc is not readable"
  66.     [ ! -r "${descdir}/use.local.desc" ] && error "${descdir}/use.local.desc is not readable"
  67.     [ ! -r "$(get_make_defaults)" ] && error "$(get_make_defaults) is not readable"
  68.     [ "${MODE}" == "modify" -a ! -w "${MAKE_CONF_PATH}" ] && error ""${MAKE_CONF_PATH}" is not writable"
  69. }
  70.  
  71. showhelp() {
  72.     echo "${PROGRAM_NAME} v${PROGRAM_VERSION}"
  73.     echo
  74.     echo "Syntax: ${PROGRAM_NAME} <option> [suboptions] [useflaglist]"
  75.     echo
  76.     echo "Options: -h, --help      - show this message"
  77.     echo "         -v, --version   - show version information"
  78.     echo "         -i, --info      - show descriptions for the given useflags"
  79.     echo "         -g, --global    - show only global use flags (suboption)"
  80.     echo "         -l, --local     - show only local use flags (suboption)"
  81.     echo "         -a, --active    - show currently active useflags and their origin"
  82.     echo "         -E, --enable    - enable the given useflags"
  83.     echo "         -D, --disable   - disable the given useflags"
  84.     echo "         -P, --prune     - remove all references to the given flags from"
  85.     echo "                           make.conf to revert to default settings"
  86.     echo
  87.     echo "Notes: ${PROGRAM_NAME} currently only works for global flags defined"
  88.     echo "       in make.globals, make.defaults or make.conf, it doesn't handle"
  89.     echo "       use.defaults, use.mask or package.use yet (see portage(5) for details on"
  90.     echo "       these files). It also might have issues with cascaded profiles."
  91.     echo "       If multiple options are specified only the last one will be used."
  92. }
  93.  
  94. showversion() {
  95.     echo "${PROGRAM_NAME} v${PROGRAM_VERSION}"
  96.     echo "Written by Marius Mauch"
  97.     echo
  98.     echo "Copyright (C) 2004 Gentoo Foundation, Inc."
  99.     echo "This is free software; see the source for copying conditions."
  100. }
  101.  
  102. # the following function creates a bash array ACTIVE_FLAGS that contains the
  103. # global use flags, indexed by origin: 0: environment, 1: make.conf, 
  104. # 2: make.defaults, 3: make.globals
  105. get_useflags() {
  106.     # only calculate once as calling emerge is painfully slow
  107.     [ -n "${USE_FLAGS_CALCULATED}" ] && return
  108.     
  109.     # backup portdir so get_portdir() doesn't give false results later
  110.     portdir_backup="${PORTDIR}"
  111.  
  112.     ACTIVE_FLAGS[0]="${USE}"
  113.     USE=""
  114.     source "${MAKE_CONF_PATH}"
  115.     ACTIVE_FLAGS[1]="${USE}"
  116.     USE=""
  117.     for x in $(get_all_make_defaults); do
  118.         source "${x}"
  119.         ACTIVE_FLAGS[2]="${ACTIVE_FLAGS[2]} ${USE}"
  120.     done
  121.     USE=""
  122.     source "${MAKE_GLOBALS_PATH}"
  123.     ACTIVE_FLAGS[3]="${USE}"
  124.  
  125.     # restore saved env variables
  126.     USE="${ACTIVE_FLAGS[0]}"
  127.     PORTDIR="${portdir_backup}"
  128.  
  129.     # get the currently active USE flags as seen by portage, this has to be after
  130.     # restoring USE or portage won't see the original environment
  131.     ACTIVE_FLAGS[9]="$(emerge --info | grep 'USE=' | cut -b 5- | sed -e 's:"::g')" #'
  132.     USE_FLAGS_CALCULATED=1
  133. }
  134.  
  135. # get the list of all known USE flags by reading use.desc and/or use.local.desc
  136. # (depending on the value of $SCOPE)
  137. get_useflaglist() {
  138.     local descdir
  139.  
  140.     descdir="$(get_portdir)/profiles"
  141.     
  142.     if [ -z "${SCOPE}" -o "${SCOPE}" == "global" ]; then
  143.         egrep "^[^# ]+ +-" "${descdir}/use.desc" | cut -d\  -f 1
  144.     fi
  145.     if [ -z "${SCOPE}" -o "${SCOPE}" == "local" ]; then
  146.         egrep "^[^# :]+:[^ ]+ +-" "${descdir}/use.local.desc" | cut -d: -f 2 | cut -d\  -f 1
  147.     fi
  148. }
  149.  
  150. # get all make.defaults by traversing the cascaded profile directories
  151. get_all_make_defaults() {
  152.     local curdir
  153.     local parent
  154.     local rvalue
  155.     
  156.     curdir="$(readlink -f ${MAKE_PROFILE_PATH})"
  157.     
  158.     while [ -f "${curdir}/parent" ]; do
  159.         [ -f "${curdir}/make.defaults" ] && rvalue="${curdir}/make.defaults ${rvalue}"
  160.         parent="$(egrep -v '(^#|^ *$)' ${curdir}/parent)"
  161.         curdir="$(readlink -f ${curdir}/${parent})"
  162.     done
  163.  
  164.     echo "${rvalue}"
  165. }
  166.  
  167. # get the path to make.defaults by traversing the cascaded profile directories
  168. get_make_defaults() {
  169.     local curdir
  170.     local parent
  171.     
  172.     curdir="$(readlink -f ${MAKE_PROFILE_PATH})"
  173.     
  174.     while [ ! -f "${curdir}/make.defaults" -a -f "${curdir}/parent" ]; do
  175.         parent="$(egrep -v '(^#|^ *$)' ${curdir}/parent)"
  176.         curdir="$(readlink -f ${curdir}/${parent})"
  177.     done
  178.  
  179.     echo "${curdir}/make.defaults"
  180. }
  181.  
  182. # little helper function to get the status of a given flag in one of the 
  183. # ACTIVE_FLAGS elements. Arguments are 1: flag to test, 2: index of ACTIVE_FLAGS,
  184. # 3: echo value for positive (and as lowercase for negative) test result, 
  185. # 4 (optional): echo value for "missing" test result, defaults to blank
  186. get_flagstatus_helper() {
  187.     if echo " ${ACTIVE_FLAGS[${2}]} " | grep " ${1} " > /dev/null; then
  188.         echo -n "${3}"
  189.     elif echo " ${ACTIVE_FLAGS[${2}]} " | grep " -${1} " > /dev/null; then
  190.         echo -n "$(echo ${3} | tr [[:upper:]] [[:lower:]])"
  191.     else
  192.         echo -n "${4:- }"
  193.     fi
  194. }
  195.  
  196. # prints a status string for the given flag, each column indicating the presence
  197. # for portage, in the environment, in make.conf, in make.defaults and in make.globals.
  198. # full positive value would be "[+ECDG]", full negative value would be [-ecdg],
  199. # full missing value would be "[-    ]" (portage only sees present or not present)
  200. get_flagstatus() {
  201.     get_useflags
  202.  
  203.     echo -n '['
  204.     get_flagstatus_helper "${1}" 9 "+" "-"
  205.     get_flagstatus_helper "${1}" 0 "E"
  206.     get_flagstatus_helper "${1}" 1 "C"
  207.     get_flagstatus_helper "${1}" 2 "D"
  208.     get_flagstatus_helper "${1}" 3 "G"
  209.     echo -n '] '
  210. }
  211.  
  212. # faster replacement to `portageq portdir`
  213. get_portdir() {
  214.     if [ -z "${PORTDIR}" ]; then
  215.         use_backup="${USE}"
  216.         source "${MAKE_GLOBALS_PATH}"
  217.         for x in $(get_all_make_defaults); do
  218.             source "${x}"
  219.         done
  220.         source "${MAKE_CONF_PATH}"
  221.         USE="${use_backup}"
  222.     fi
  223.     echo "${PORTDIR}"
  224. }
  225.  
  226. # This function takes a list of use flags and shows the status and 
  227. # the description for each one, honoring $SCOPE
  228. showdesc() {
  229.     local descdir
  230.     local current_desc
  231.     local found_one
  232.     local args
  233.     
  234.     args="${*:-*}"
  235.     
  236.     if [ -z "${SCOPE}" ]; then
  237.         SCOPE="global" showdesc ${args}
  238.         echo
  239.         SCOPE="local" showdesc ${args}
  240.         return
  241.     fi
  242.     
  243.     descdir="$(get_portdir)/profiles"
  244.     
  245.     [ "${SCOPE}" == "global" ] && echo "global use flags (searching: ${args})"
  246.     [ "${SCOPE}" == "local" ] && echo "local use flags (searching: ${args})"
  247.     echo "************************************************************"
  248.     
  249.     if [ "${args}" == "*" ]; then
  250.         args="$(get_useflaglist | sort -u)"
  251.     fi
  252.     
  253.     set ${args}
  254.     
  255.     foundone=0
  256.     while [ -n "${1}" ]; do
  257.         if [ "${SCOPE}" == "global" ]; then
  258.             if grep "^${1}  *-" "${descdir}/use.desc" > /dev/null; then
  259.                 get_flagstatus "${1}"
  260.                 foundone=1
  261.             fi
  262.             grep "^${1}  *-" "${descdir}/use.desc"
  263.         fi
  264.         # local flags are a bit more complicated as there can be multiple 
  265.         # entries per flag and we can't pipe into printf
  266.         if [ "${SCOPE}" == "local" ]; then
  267.             if grep ":${1}  *-" "${descdir}/use.local.desc" > /dev/null; then
  268.                 foundone=1
  269.             fi
  270.             grep ":${1}  *-" "${descdir}/use.local.desc" \
  271.                 | sed -e "s/^\([^:]\+\):\(${1}\) *- *\(.\+\)/\1|\2|\3/g" \
  272.                 | while read line; do
  273.                     pkg="$(echo $line | cut -d\| -f 1)"
  274.                     flag="$(echo $line | cut -d\| -f 2)"
  275.                     desc="$(echo $line | cut -d\| -f 3)"
  276.                     get_flagstatus "${flag}"
  277.                     printf "%s (%s):\n%s\n\n" "${flag}" "${pkg}" "${desc}"
  278.                 done
  279.         fi
  280.         shift
  281.     done
  282.     
  283.     if [ ${foundone} == 0 ]; then
  284.         echo "no matching entries found"
  285.     fi
  286. }
  287.  
  288. # show a list of all currently active flags and where they are activated
  289. showflags() {
  290.     local args
  291.  
  292.     get_useflags
  293.     
  294.     args="${*:-*}"
  295.     
  296.     if [ "${args}" == "*" ]; then
  297.         args="$(get_useflaglist | sort -u)"
  298.     fi
  299.     
  300.     set ${args}
  301.     
  302.     while [ -n "${1}" ]; do
  303.         if echo " ${ACTIVE_FLAGS[9]} " | grep " ${1} " > /dev/null; then
  304.             printf "%-20s" ${1}
  305.             get_flagstatus ${1}
  306.             echo
  307.         fi
  308.         shift
  309.     done
  310. }
  311.  
  312. # two small helpers to add or remove a flag from a USE string
  313. add_flag() {
  314.     NEW_MAKE_CONF_USE="${NEW_MAKE_CONF_USE} ${1}"
  315. }
  316.  
  317. remove_flag() {
  318.     NEW_MAKE_CONF_USE="${NEW_MAKE_CONF_USE// ${1} / }"
  319. }
  320.  
  321. # USE flag modification function. Mainly a loop with calls to add_flag and 
  322. # remove_flag to create a new USE string which is then inserted into make.conf.
  323. modify() {
  324.     if [ -z "${*}" ]; then
  325.         if [ "${ACTION}" != "prune" ]; then
  326.             echo "WARNING: no USE flags listed for modification, do you really"
  327.             echo "         want to ${ACTION} *all* known USE flags?"
  328.             echo "         If you don't please press Ctrl-C NOW!!!"
  329.             sleep 5
  330.             set $(get_useflaglist | sort -u)
  331.         fi
  332.     fi
  333.     
  334.     get_useflags
  335.     
  336.     NEW_MAKE_CONF_USE=" ${ACTIVE_FLAGS[1]} "
  337.     
  338.     while [ -n "${1}" ]; do
  339.         if [ "${ACTION}" == "add" ]; then
  340.             if echo " ${NEW_MAKE_CONF_USE} " | grep " ${1} " > /dev/null; then
  341.                 shift
  342.             elif echo " ${NEW_MAKE_CONF_USE} " | grep " -${1} " > /dev/null; then
  343.                 remove_flag "-${1}"
  344.             else
  345.                 add_flag "${1}"
  346.                 shift
  347.             fi
  348.         elif [ "${ACTION}" == "remove" ]; then
  349.             if echo " ${NEW_MAKE_CONF_USE} " | grep " -${1} " > /dev/null; then
  350.                 shift
  351.             elif echo " ${NEW_MAKE_CONF_USE} " | grep " ${1} " > /dev/null; then
  352.                 remove_flag "${1}"
  353.             else
  354.                 add_flag "-${1}"
  355.                 shift
  356.             fi
  357.         elif [ "${ACTION}" == "prune" ]; then
  358.             if echo " ${NEW_MAKE_CONF_USE} " | grep " ${1} " > /dev/null; then
  359.                 remove_flag "${1}"
  360.             elif echo " ${NEW_MAKE_CONF_USE} " | grep " -${1} " > /dev/null; then
  361.                 remove_flag "-${1}"
  362.             fi
  363.             shift
  364.         fi
  365.     done
  366.     
  367.     #echo "old flags:"
  368.     #echo ${ACTIVE_FLAGS[1]}
  369.     #echo
  370.     #echo "new flags:"
  371.     #echo ${NEW_MAKE_CONF_USE}
  372.     
  373.     # a little loop to add linebreaks so we don't end with one ultra-long line
  374.     NEW_MAKE_CONF_USE_2=""
  375.     for x in ${NEW_MAKE_CONF_USE}; do
  376.         if [ $(((${#NEW_MAKE_CONF_USE_2}%70)+${#x}+2)) -gt 70 ]; then
  377.             NEW_MAKE_CONF_USE_2="${NEW_MAKE_CONF_USE_2}\\ \\n     $x "
  378.         else
  379.             NEW_MAKE_CONF_USE_2="${NEW_MAKE_CONF_USE_2}${x} "
  380.         fi
  381.     done
  382.  
  383.     # make a backup just in case the user doesn't like the new make.conf
  384.     cp -p "${MAKE_CONF_PATH}" "${MAKE_CONF_BACKUP_PATH}"
  385.     
  386.     # as sed doesn't really work with multi-line patterns we have to replace USE
  387.     # on our own here. Basically just skip everything between USE=" and the 
  388.     # closing ", printing our new USE line there instead.
  389.     inuse=0
  390.     (while read -r line; do
  391.         [ "${line:0:4}" == "USE=" ] && inuse=1
  392.         [ "${inuse}" == "0" ] && echo -E "${line}"
  393.         if [ "${inuse}" == "1" ] && echo "${line}" | egrep '" *(#.*)?$' > /dev/null; then
  394.             echo -n 'USE="'
  395.             echo -ne "${NEW_MAKE_CONF_USE_2%% }"
  396.             echo '"'
  397.              inuse=0
  398.         fi
  399.     done ) < "${MAKE_CONF_BACKUP_PATH}" | sed -e 's:\\ $:\\:' > "${MAKE_CONF_PATH}"
  400.     
  401.     echo "${MAKE_CONF_PATH} was modified, a backup copy has been placed at ${MAKE_CONF_BACKUP_PATH}"
  402. }
  403.  
  404. ##### main program comes now #####
  405.  
  406. # disable globbing as it fucks up with args=*
  407. set -f
  408. parse_arguments "$@"
  409. check_sanity
  410.  
  411. eval ${MODE} ${ARGUMENTS}
  412. set +f
  413.